package com.sunxd.rule.judge.support;

import com.sunxd.rule.judge.ConditionJudge;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Objects;

@Slf4j
public abstract class AbstractConditionSupportJudge implements ConditionJudge {


    @Override
    public Boolean gt(Object left, Object right) {
        if (!isParentChild(left, right)) {
            log.error(" Different classes =>  left : {}, right : {} ", Objects.isNull(left) ? "null" : left.getClass(), Objects.isNull(right) ? "null" : right.getClass());
            return Boolean.FALSE;
        }
        return getResult(left,right) > 0;
    }

    @Override
    public Boolean lt(Object left, Object right) {
        if (!isParentChild(left, right)) {
            log.error(" Different classes =>  left : {}, right : {} ", Objects.isNull(left) ? "null" : left.getClass(), Objects.isNull(right) ? "null" : right.getClass());
            return Boolean.FALSE;
        }
        return getResult(left,right) < 0;
    }

    private int getResult(Object left, Object right) {
        int result = 0;
        if (eq(left, right)) {
            return result;
        }
        if (right instanceof Integer) {
            result = Integer.compare((Integer) left, (Integer) right);
        } else if (right instanceof Double) {
            result = Double.compare((Double) left, (Double) right);
        } else if (right instanceof Long) {
            result = Long.compare((Long) left, (Long) right);
        } else if (right instanceof Date) {
            result = ((Date) left).after((Date) right) ? 1 : -1;
        }else if (right instanceof LocalDate) {
            result = ((LocalDate) left).isAfter((LocalDate) right) ? 1 : -1;
        }else if (right instanceof LocalDateTime) {
            result = ((LocalDateTime) left).isAfter((LocalDateTime) right) ? 1 : -1;
        } else {
            log.error("method is not definition => classType : " + right.getClass());
        }
        return result;
    }

    @Override
    public Boolean eq(Object left, Object right) {
        return Objects.equals(left, right);
    }

    @Override
    public Boolean in(Object left, Object right) {
        boolean result = Boolean.FALSE;
        if (right instanceof Collection) {
            for (Iterator iterator = ((Collection) right).iterator(); iterator.hasNext(); ) {
                Object next = iterator.next();
                if (eq(next, left)) {
                    result = Boolean.TRUE;
                    break;
                }
            }

        }
        return result;
    }

    public static boolean isParentChild(Object parent, Object child) {
        if (parent == null || child == null) {
            return false;
        }
        return child.getClass().isAssignableFrom(parent.getClass()) ||
                parent.getClass().isAssignableFrom(child.getClass());
    }

}
